#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "common.h"

#define CREATER "creater"
#define USER "user"
#define PATH "."
#define PROJID 0x66
#define DEFAULT_SIZE 4096
#define DEFAULT_MODE 0666


class Shm
{
private:
    int CreateHelper(int flag)
    {
        _shmid = shmget(_key, DEFAULT_SIZE, flag); // 创建全新的共享内存
        if (_shmid < 0)
            ERR_EXIT("shmget");
        std::cout << "shmid:" << _shmid << std::endl;
        return _shmid;
    }

    void Detech()
    {
        int n = shmdt(_virtual_add);
        if (n < 0)
            ERR_EXIT("shmdt");
        std::cout << "detech success!" << std::endl;
    }

    void Destory()
    {
        int n = shmctl(_shmid, IPC_RMID, nullptr);
        if (n < 0)
            ERR_EXIT("shmctl");
        std::cout << "destory success!" << std::endl;
    }

public:
    Shm(const char *path, int proj_id, const std::string user_type) : _user_type(user_type)
    {
        // 构造函数-获取key
        _key = ftok(path, proj_id);
        if (ftok < 0)
            ERR_EXIT("ftok");
    }
    int CreateOrGet()
    {
        if (_user_type == CREATER)
            return CreateHelper(IPC_CREAT | IPC_EXCL | DEFAULT_MODE);
        else if (_user_type == USER)
        {
            return CreateHelper(IPC_CREAT);
        }
        else
        {
            return -1;
        }
    }

    void *Attach()
    {
        _virtual_add = shmat(_shmid, nullptr, 0);
        if ((long long)_virtual_add == -1)
            ERR_EXIT("shmat");
        std::cout << "attach success!" << std::endl;
        return _virtual_add;
    }

    ~Shm()
    {
        Detech();
        if (_user_type == CREATER)
        {
            Destory();
        }
       
    }

private:
    std::string _user_type;
    int _shmid;
    int _key;
    void *_virtual_add;
};